package com.ruoyi.boc.service.impl;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.ruoyi.boc.domain.BocLakeImport;
import com.ruoyi.boc.domain.BocLakeTableColumn;
import com.ruoyi.boc.mapper.BocLakeTableColumnMapper;
import com.ruoyi.boc.utils.LakeVelocityUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.util.VelocityInitializer;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.boc.mapper.BocLakeTableMapper;
import com.ruoyi.boc.domain.BocLakeTable;
import com.ruoyi.boc.service.IBocLakeTableService;

import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 入湖生成业务Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-02-14
 */
@Service
public class BocLakeTableServiceImpl implements IBocLakeTableService 
{

    private static final Logger log = LoggerFactory.getLogger(BocLakeTableServiceImpl.class);

    @Autowired
    private BocLakeTableMapper bocLakeTableMapper;
    @Autowired
    private BocLakeTableColumnMapper bocLakeTableColumnMapper;

    /**
     * 查询入湖生成业务
     * 
     * @param tableId 入湖生成业务主键
     * @return 入湖生成业务
     */
    @Override
    public BocLakeTable selectBocLakeTableByTableId(Long tableId)
    {
        return bocLakeTableMapper.selectBocLakeTableByTableId(tableId);
    }

    /**
     * 查询入湖生成业务列表
     * 
     * @param bocLakeTable 入湖生成业务
     * @return 入湖生成业务
     */
    @Override
    public List<BocLakeTable> selectBocLakeTableList(BocLakeTable bocLakeTable)
    {
        return bocLakeTableMapper.selectBocLakeTableList(bocLakeTable);
    }

    /**
     * 新增入湖生成业务
     * 
     * @param bocLakeTable 入湖生成业务
     * @return 结果
     */
    @Override
    public int insertBocLakeTable(BocLakeTable bocLakeTable)
    {
        bocLakeTable.setCreateTime(DateUtils.getNowDate());
        return bocLakeTableMapper.insertBocLakeTable(bocLakeTable);
    }

    /**
     * 修改入湖生成业务
     * 
     * @param bocLakeTable 入湖生成业务
     * @return 结果
     */
    @Override
    public int updateBocLakeTable(BocLakeTable bocLakeTable)
    {
        bocLakeTable.setUpdateTime(DateUtils.getNowDate());
        return bocLakeTableMapper.updateBocLakeTable(bocLakeTable);
    }

    /**
     * 批量删除入湖生成业务
     * 
     * @param tableIds 需要删除的入湖生成业务主键
     * @return 结果
     */
    @Override
    public int deleteBocLakeTableByTableIds(Long[] tableIds)
    {
        return bocLakeTableMapper.deleteBocLakeTableByTableIds(tableIds);
    }

    /**
     * 删除入湖生成业务信息
     * 
     * @param tableId 入湖生成业务主键
     * @return 结果
     */
    @Override
    public int deleteBocLakeTableByTableId(Long tableId)
    {
        return bocLakeTableMapper.deleteBocLakeTableByTableId(tableId);
    }

    @Override
    public List<BocLakeTable> selectGbaseTableList(BocLakeTable bocLakeTable) {
        return bocLakeTableMapper.selectGbaseTableList(bocLakeTable);
    }

    @Override
    public List<BocLakeTable> selectGbaseTableListByNames(String[] tableNames) {
        return bocLakeTableMapper.selectGbaseTableListByNames(tableNames);
    }

//    @Override
//    public void importGbaseTable(List<BocLakeTable> tableList) {
//        String operName = SecurityUtils.getUsername();
//        try
//        {
//            for (BocLakeTable table : tableList)
//            {
//                String tableName = table.getTableName();
//                long row = bocLakeTableMapper.insertBocLakeTable(table);
//                if (row > 0)
//                {
//                    // 保存列信息
//                    List<BocLakeTableColumn> bocLakeTableColumns = bocLakeTableColumnMapper.selectGbaseTableColumnsByName(tableName);
//                    for (BocLakeTableColumn column : bocLakeTableColumns)
//                    {
//                        column.setTableId(table.getTableId());
//                        bocLakeTableColumnMapper.insertBocLakeTableColumn(column);
//                    }
//                }
//            }
//        }
//        catch (Exception e)
//        {
//            throw new ServiceException("导入失败：" + e.getMessage());
//        }
//    }

    @Override
    public void importGbaseTable(List<BocLakeTable> tableList) {
        String operName = SecurityUtils.getUsername();
        try
        {
            for (BocLakeTable table : tableList)
            {
                String tableName = table.getTableName();
                long row = bocLakeTableMapper.insertBocLakeTable(table);
                if (row > 0)
                {
                    // 保存列信息
                    List<BocLakeTableColumn> batchList = new ArrayList<BocLakeTableColumn>();
                    List<BocLakeTableColumn> bocLakeTableColumns = bocLakeTableColumnMapper.selectGbaseTableColumnsByName(tableName);
                    for (BocLakeTableColumn column : bocLakeTableColumns)
                    {
                        column.setTableId(table.getTableId());
                        batchList.add(column);
                    }
                    bocLakeTableColumnMapper.insertBocLakeTableColumnBatch(batchList);
                }
            }
        }
        catch (Exception e)
        {
            throw new ServiceException("导入失败：" + e.getMessage());
        }
    }

    @Override
    public void downloadLakeCode(HttpServletResponse response, long tableId) throws IOException {
        List<String> columnList= bocLakeTableColumnMapper.selectLakeTableColumnsByTableId(tableId);
        BocLakeTable bocLakeTable = bocLakeTableMapper.selectBocLakeTableByTableId(tableId);
        String cycle = bocLakeTable.getCycle();
        VelocityContext context = LakeVelocityUtils.prepareLakeContext(columnList,bocLakeTable);
        // 设置响应内容类型
        response.setContentType("application/octet-stream");

        // 设置Content-Disposition头以触发下载
        String fileName = bocLakeTable.getTableName()+"_lake"; // 你可以根据需要动态设置文件名
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        //初始化模板引擎
        VelocityInitializer.initVelocity();

        // 渲染模板
        Template template = new Template();
        StringWriter sw = new StringWriter();
        if(cycle.equals("D")){
            template = Velocity.getTemplate("vm/sh/lake_d.vm","UTF-8");
        }else if(cycle.equals("M")){
            template = Velocity.getTemplate("vm/sh/lake_m.vm","UTF-8");
        }
        // 创建 OutputStream 和 Writer
        // 将模板渲染结果写入响应输出流
        try (Writer writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8")) {
            template.merge(context, writer);
            writer.flush();
        }
    }

    @Override
    public byte[] downloadLakeCode(Long[] tableIds) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        for (Long tableId : tableIds)
        {
            generatorLakeCode(tableId, zip);
        }
        IOUtils.closeQuietly(zip);
        return outputStream.toByteArray();
    }

    /**
     * 查询表信息并生成代码
     */
    private void generatorLakeCode(Long tableId, ZipOutputStream zip)
    {
        List<String> colList= bocLakeTableColumnMapper.selectLakeTableColumnsByTableId(tableId);
        BocLakeTable bocLakeTable = bocLakeTableMapper.selectBocLakeTableByTableId(tableId);
        String cycle = bocLakeTable.getCycle();
        VelocityContext context = LakeVelocityUtils.prepareLakeContext(colList,bocLakeTable);

        //初始化模板引擎
        VelocityInitializer.initVelocity();

        //创建上下文并填充数据

        // 渲染模板
        Template template = new Template();
        StringWriter sw = new StringWriter();
        if(cycle.equals("D")){
            template = Velocity.getTemplate("vm/sh/lake_d.vm","UTF-8");
        }else if(cycle.equals("M")){
            template = Velocity.getTemplate("vm/sh/lake_m.vm","UTF-8");
        }
        template.merge(context, sw);
        try
        {
            // 添加到zip
            zip.putNextEntry(new ZipEntry(bocLakeTable.getTableName()+"_lake.sh"));
            IOUtils.write(sw.toString(), zip, Constants.UTF8);
            IOUtils.closeQuietly(sw);
            zip.flush();
            zip.closeEntry();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public LinkedList<String> selectLakeTableColumnsByName(String tableName) {
        return bocLakeTableMapper.selectLakeTableColumnsByName(tableName);
    }

    @Override
    public void synchGbaseDb(String tableName) {
        BocLakeTable table = bocLakeTableMapper.selectBocLakeTableByName(tableName);
        List<BocLakeTableColumn> tableColumns = table.getColumns();
        Map<String, BocLakeTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(BocLakeTableColumn::getColumnName, Function.identity()));

        List<BocLakeTableColumn> gbaseTableColumns = bocLakeTableColumnMapper.selectGbaseTableColumnsByName(tableName);
        if (StringUtils.isEmpty(gbaseTableColumns)) {
            throw new ServiceException("同步数据失败，原表结构不存在");
        }
        List<String> gbaseTableColumnNames = gbaseTableColumns.stream().map(BocLakeTableColumn::getColumnName).collect(Collectors.toList());

        gbaseTableColumns.forEach(column -> {
            column.setTableId(table.getTableId());
            if (tableColumnMap.containsKey(column.getColumnName())) {
                BocLakeTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
                column.setColumnId(prevColumn.getColumnId());
                bocLakeTableColumnMapper.updateBocLakeTableColumn(column);
            } else {
                bocLakeTableColumnMapper.insertBocLakeTableColumn(column);
            }
        });
        List<BocLakeTableColumn> delColumns = tableColumns.stream().filter(column -> !gbaseTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
        if (StringUtils.isNotEmpty(delColumns)) {
            bocLakeTableColumnMapper.deleteLakeTableColumns(delColumns);
        }
    }

    @Override
    public String previewLakeCode(Long tableId) {
        List<String> columnList= bocLakeTableColumnMapper.selectLakeTableColumnsByTableId(tableId);
        BocLakeTable bocLakeTable = bocLakeTableMapper.selectBocLakeTableByTableId(tableId);
        String cycle = bocLakeTable.getCycle();
        VelocityContext context = LakeVelocityUtils.prepareLakeContext(columnList,bocLakeTable);

        //初始化模板引擎
        VelocityInitializer.initVelocity();

        // 渲染模板
        Template template = new Template();
        if(cycle.equals("D")){
            template = Velocity.getTemplate("vm/sh/lake_d.vm","UTF-8");
        }else if(cycle.equals("M")){
            template = Velocity.getTemplate("vm/sh/lake_m.vm","UTF-8");
        }

        // 渲染模板
        StringWriter sw = new StringWriter();
        template.merge(context, sw);
        return sw.toString();
    }

    @Override
    public String importBocLakeData(List<BocLakeImport> bocLakeImportList, Boolean isUpdateSupport, String operName) {
        if (StringUtils.isNull(bocLakeImportList) || bocLakeImportList.size() == 0)
        {
            throw new ServiceException("导入用户数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        List<BocLakeImport> lakeTables = getBocLakeName(bocLakeImportList);
        for (BocLakeImport lakeTable : lakeTables)
        {
            String tableName = lakeTable.getTableNameEn();
            String tableComment = lakeTable.getTableNameCn();
            try
            {
                // 验证表是否存在
                BocLakeTable bkt = bocLakeTableMapper.selectBocLakeTableByName(tableName);
                if (StringUtils.isNull(bkt)) {
                    BocLakeTable bocLakeTable = new BocLakeTable();
                    bocLakeTable.setTableName(tableName);
                    bocLakeTable.setTableComment(tableComment);
                    this.insertBocLakeTable(bocLakeTable);
                    bkt = bocLakeTableMapper.selectBocLakeTableByName(tableName);
                    Long tableId = bkt.getTableId();
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、表 " + tableName + " 导入成功");
                    List<BocLakeImport> blcList = getBocLakeColumn(tableName, bocLakeImportList);
                    List<BocLakeTableColumn> batchList = new ArrayList<BocLakeTableColumn>();
                    for (int i = 0; i < blcList.size(); i++) {
                        BocLakeTableColumn bocLakeTableColumn = new BocLakeTableColumn();
                        bocLakeTableColumn.setTableId(tableId);
                        bocLakeTableColumn.setColumnName(blcList.get(i).getColumnNameEn());
                        bocLakeTableColumn.setColumnComment(blcList.get(i).getColumnNameCn());
                        bocLakeTableColumn.setSort(blcList.get(i).getColumnSort());
                        //bocLakeTableColumnMapper.insertBocLakeTableColumn(bocLakeTableColumn);
                        batchList.add(bocLakeTableColumn);
                    }
                    bocLakeTableColumnMapper.insertBocLakeTableColumnBatch(batchList);
                }
                else if (isUpdateSupport)
                {
                    bocLakeTableMapper.deleteBocLakeTableByTableName(tableName);
                    Long[] tableIds = new Long[3];
                    tableIds[0] = bkt.getTableId();
                    bocLakeTableColumnMapper.deleteBocLakeTableColumnByTableIds(tableIds);
                    BocLakeTable bocLakeTable = new BocLakeTable();
                    bocLakeTable.setTableName(tableName);
                    bocLakeTable.setTableComment(tableComment);
                    this.insertBocLakeTable(bocLakeTable);
                    bkt = bocLakeTableMapper.selectBocLakeTableByName(tableName);
                    Long tableId = bkt.getTableId();
                    List<BocLakeImport> blcList = getBocLakeColumn(tableName, bocLakeImportList);
                    List<BocLakeTableColumn> batchList = new ArrayList<BocLakeTableColumn>();
                    for (int i = 0; i < blcList.size(); i++) {
                        BocLakeTableColumn bocLakeTableColumn = new BocLakeTableColumn();
                        bocLakeTableColumn.setTableId(tableId);
                        bocLakeTableColumn.setColumnName(blcList.get(i).getColumnNameEn());
                        bocLakeTableColumn.setColumnComment(blcList.get(i).getColumnNameCn());
                        bocLakeTableColumn.setSort(blcList.get(i).getColumnSort());
                        //bocLakeTableColumnMapper.insertBocLakeTableColumn(bocLakeTableColumn);
                        batchList.add(bocLakeTableColumn);
                    }
                    bocLakeTableColumnMapper.insertBocLakeTableColumnBatch(batchList);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、表 " + tableName + " 更新成功");
                }
                else
                {
                    failureNum++;
                    failureMsg.append("<br/>" + failureNum + "、表 " + tableName + " 已存在");
                }
            }
            catch (Exception e)
            {
                failureNum++;
                String msg = "<br/>" + failureNum + "、表 " + tableName + " 导入失败：";
                failureMsg.append(msg + e.getMessage());
                log.error(msg, e);
            }
        }
        if (failureNum > 0)
        {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        }
        else
        {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    @Override
    public int deleteBocLakeTableByTableName(String tableName) {
        return bocLakeTableMapper.deleteBocLakeTableByTableName(tableName);
    }

    private List<BocLakeImport> getBocLakeName (List<BocLakeImport> bocLakeImportList){
        List<String> tableNameList = new ArrayList<String>();
        List<BocLakeImport> arr = new ArrayList<BocLakeImport>();
        for(int i=0;i<bocLakeImportList.size();i++){
            String tableName = bocLakeImportList.get(i).getTableNameEn();
            if(!tableNameList.contains(tableName)){
                arr.add(bocLakeImportList.get(i));
            }
            tableNameList.add(tableName);
        }
        return arr;
    }

    private List<BocLakeImport> getBocLakeColumn (String tableName, List<BocLakeImport> bocLakeImportList){
        List<BocLakeImport> result = new ArrayList<BocLakeImport>();
        for (BocLakeImport record : bocLakeImportList) {
            if (tableName.equals(record.getTableNameEn())) {
                result.add(record); // 将符合条件的记录添加到结果列表
            }else{
                return result;
            }
        }
        return result;
    }
}
